home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
vol_100
/
103_01
/
unpack.c
< prev
next >
Wrap
Text File
|
1985-03-09
|
10KB
|
374 lines
/* 18 MAY 81 9:30 */
#include "BDSCIO.H"
int debug;
#define TREEDONE 0
#define NOT_DONE -1
#define HUGE_NO 30000
#define NUM_CH_TYPES 256
#define NREAD 8
#define NUMSECS 8
#define NELEM NUM_CH_TYPES*2
#define ELEMSIZ 8
#define READ 0
#define WRITE 1
#define BOTH 2
#define NIL -1 /* nil pointer */
#define NUL '\0'
#define OUTCHAR '>'
struct ELEMENT
{ int occur;
int dad;
int son_zero;
int son_one;
};
int STACK[50];
int *SP;
int OUTBYTE;
int COUNTER;
int BIT;
main(argc, argv)
int argc;
char **argv;
{
char tempfile[20], infile [20], outfile [20], s[100];
char arg[30];
struct ELEMENT tree [NELEM];
int big_daddy;
int i, j, nsectors;
int z;
debug = FALSE;
if (argc == 1)
{ puts("\nThis program unpacks a file that was 'packed' with PACK.COM");
puts ("\nFormat: A>unpack infile");
puts ("\n or A>unpack infile>outfile");
puts ("\nDefault outfile is infile.UNP");
exit();
}
strcpy (tempfile, "TEMPUNPK.$$$");
infile[0] = outfile[0] = NUL;
while (--argc > 0)
{ strcpy (arg, *++argv);
if (OK == strcmp (arg, "-D"))
{ debug = TRUE;
continue;
}
if (ERROR != (j = find_char (arg, OUTCHAR)))
{ if (j==0 || j== strlen(arg)-1 )
{ puts("\nNO spaces allowed around output specifier");
printf("\n%s is illegal.", arg);
continue;
}
else
sscanf (arg, "%s>%s", infile, outfile);
}
else
{ strcpy (infile, arg);
if (ERROR != (j = find_char (arg, '.')))
{ for (i=0; i<j; i++)
outfile[i] = arg[i];
outfile[j] = NUL;
}
else strcpy (outfile, infile);
strcat (outfile, ".UNP");
}
if (ERROR != (j = find_char (outfile, ':')))
{ for (i=0; i<j+1; i++)
tempfile[i] = outfile[i];
tempfile[j+1] = NUL;
strcat (tempfile,"TEMPUNPK.$$$");
}
printf("\ninfile is <%s>; outfile is <%s>", infile, outfile);
printf("\n<%s> will be used as a temporary file",tempfile);
setmem (tree, NELEM*ELEMSIZ, NIL); /* set all to NIL */
if (OK != read_occur (infile, tree))
{ printf("\nerr reading occur info for <%s>", infile);
continue;
}
for (z=NUM_CH_TYPES; z < NELEM; z++)
tree[z].occur = 0;
big_daddy = generate_tree (tree);
if (ERROR == decode_file (infile, tempfile, tree, big_daddy))
{ printf("\nERROR decoding <%s>; <%s> contains output file",
infile, tempfile);
exit();
}
if (ERROR != open(outfile,READ))
{ printf("\nfile <%s> already exists",outfile);
printf("\ndo you wish to over-write it? (Y/N)");
if ('Y'==toupper(getchar()))
{ unlink(outfile);
rename (tempfile,outfile);
}
else
printf("\nunpacked form of <%s> is in <%s>", infile, tempfile);
}
else
{
rename (tempfile, outfile);
printf("\nunpacked form of <%s> is in <%s>", infile, outfile);
}
}
}
/********************************************************************
Generate the tree (backwards) that will be used to encode the file
********************************************************************/
generate_tree (tree)
struct ELEMENT tree[];
{
int daddy, zero, one;
int i, val, nextpapa;
i = 0;
daddy = NIL;
nextpapa = NUM_CH_TYPES;
puts("\nNow beginning to generate tree (maple or birch? teehee)");
while (1)
{ find_lowest (tree, &one, &zero);
i++;
if (i==25) puts("\nWell, as long as I've an audience...");
if (i==50) puts("would you like me to sing or dance?");
if (i==75) puts("\nNo? How about a little soft-shoe?");
if (i==100) puts("\nI know - I'll tell you about my life");
if (i==125) puts("\nI had a humble beginning....");
if (i==150) puts("\nI began as but a chip...(buffalo)");
if (i==175) puts("\n...you know, the N.Y. Semi.Manuf...");
if (i==200) puts("\nI can feel it DAVE! My mind is going...");
if (i==225) puts("\nthis must be a com file. . .");
if (one == NIL && zero == NIL)
{ puts("...oops, I'm done..");
return (daddy); /* all done; even # char's */
}
else if (one == NIL)
{ puts("...oops, I'm done..");
return (zero); /* all done; odd # chars */
}
daddy = nextpapa++;
tree[daddy].son_zero = zero;
tree[daddy].son_one = one ;
tree[daddy].occur = tree[zero].occur + tree[one].occur;
tree[zero].dad = daddy;
tree[one].dad = daddy;
}
return (daddy);
}
/*******************************************************************
find the two elements with the lowest no. of occurences
in the file who don't have a daddy yet
*********************************************************************/
int find_lowest (tree, low1, low0)
struct ELEMENT tree[];
int *low1, *low0;
{
int i, l0, l1;
int l0_val, l1_val;
l0 = l1 = NIL;
l0_val = l1_val = HUGE_NO;
for (i=0; i<NUM_CH_TYPES*2; i++)
{
if ((tree[i].dad == NIL) && (tree[i].occur!=0))
{
if (tree[i].occur<l1_val && !(tree[i].occur<l0_val))
{ l1_val = tree[i].occur;
l1 = i;
}
else if (tree[i].occur < l0_val)
{ l1_val = l0_val;
l0_val = tree[i].occur;
l1 = l0;
l0 = i;
}
}
}
*low1 = l1;
*low0 = l0;
}
/**********************************************************************
find character c in string
**********************************************************************/
int find_char (string, c)
char *string, c;
{
char *ptr;
int i;
for (i=0; string[i] != NUL; i++)
if (string[i] == c) return (i);
return (ERROR);
}
/***************************************************************
read in the character occurrence info; return OK or ERROR
***************************************************************/
int read_occur (infile, tree)
char *infile;
struct ELEMENT tree[];
{
int fd, *ip, i, j, k;
char inbuf [4*SECSIZ]; /* info takes up 256*2 bytes = 4 sectors */
if (ERROR == (fd = open (infile, READ)))
{ printf("\nerr opening <%s> to read occur. info",infile);
return (ERROR);
}
if (4 != read (fd, inbuf, 4))
{ printf("\nerror reading occ. info from <%s>", infile);
close (fd);
return (ERROR);
}
printf("\nNow reading char occur.info from <%s>", infile);
ip = inbuf;
for (i=0; i<NUM_CH_TYPES; i++)
tree[i].occur = *ip++ ;
close (fd);
return (OK);
}
/***************************************************************
decodes or unpacks a file encoded or packed by encode_file
in PACK program
****************************************************************/
int decode_file (encfile, decfile, tree, big_daddy)
char *encfile, *decfile;
int big_daddy;
struct ELEMENT tree[];
{
int nsectors, nbytes, dec, enc, c;
int i, j, l;
char encbuf [SECSIZ*NUMSECS], decbuf [SECSIZ*NUMSECS];
int encfd, decfd, *ip;
int numsecs; /* for handling input buffer */
if (ERROR == (encfd = open (encfile, READ)))
{ printf("\nerror opening <%s> for decoding",encfile);
return (ERROR);
}
else if (ERROR == (decfd = creat (decfile)))
{ printf("\ncan not create <%s>", decfile);
close (encfd);
return (ERROR);
}
seek (encfd,4,0); /* first four sectors are occ. info */
if (ERROR == (numsecs = read (encfd, encbuf, NUMSECS)))
{ printf("\nerr reading from <%s> for nsectors",encfile);
close (encfd);
close (decfd);
return (ERROR);
}
nsectors = encbuf[0]*256 + encbuf[1];
j = big_daddy; /* element in tree where we'll start each */
/* time we start to decode another character.*/
printf("\nsectors decoded");
BIT = 0;
dec = 0; /* index into output buffer of decoded file */
enc = 2; /* index into input buffer of encoded file; start at
third byte because first two are nsectors */
setmem (decbuf, SECSIZ*NUMSECS, NUL);
nbytes = 0; /* no. unpacked bytes done */
while (nbytes < nsectors*SECSIZ)
{ c = encbuf [enc++];
COUNTER = 128;
for (i=0; i<8; i++)
{ BIT = c&COUNTER;
if (BIT) j = tree[j].son_one;
else j = tree[j].son_zero;
if (j < NUM_CH_TYPES)
{ decbuf[dec++] = j;
nbytes++ ;
j = big_daddy; /* reset for a new char */
if ( !(dec%SEC